package com.wxy.ej.flow.modules.taskflow.service.nodeExecuteStrategy.strategy.controller;

import com.alibaba.fastjson.JSONObject;
import com.rt.easyjava.common.base.Result;
import com.rt.easyjava.common.config.SpringContextBaseHolder;
import com.rt.easyjava.common.utils.others.StringUtils;
import com.wxy.ej.flow.modules.taskflow.dto.DataDto;
import com.wxy.ej.flow.modules.taskflow.dto.NodeDto;
import com.wxy.ej.flow.modules.taskflow.repository.NodeRepository;
import com.wxy.ej.flow.modules.taskflow.service.nodeExecuteStrategy.NodeStrategy;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class ControllerCombineNodeStrategy extends NodeStrategy {

    public static final String Combine_Ok = "Combine_Ok";
    public static final String Combine_NotOk = "Combine_NotOk";

    private NodeRepository nodeRepository;

    @Override
    public Result action(NodeDto node, JSONObject flowDataJson, DataDto dataDto) throws Exception{
        log.info("ControllerCombineNodeStrategy");
        nodeRepository = SpringContextBaseHolder.getBean("nodeRepository");

        // 应该有几条线进，'数据汇聚'节点; 应该执行次数
        List<NodeDto> preNodeList = nodeRepository.selectPreNodeList(node.getId(), flowDataJson);

        // 当前节点执行次数
        Map<String, Object> storageControllerVarMap = dataDto.getStorageControllerVarMap();
        // 当前节点执行次数+1
        Integer nodeExecuteTimesInteger =  (Integer)dataDto.getValueFromMap(node.getId(), storageControllerVarMap);
        storageControllerVarMap.put(node.getId(), nodeExecuteTimesInteger.intValue()+1);
        int nodeExecuteTimesInt =  ((Integer) storageControllerVarMap.get(node.getId())).intValue();

        if (preNodeList.size() != nodeExecuteTimesInt) {
            log.info("ControllerCombineNodeStrategy: 数据没到齐，跳过");
            dataDto.getLogList().add("数据没到齐，跳过");
            return Result.builder(Combine_NotOk);
        }

        // 数据汇聚
        log.info("ControllerCombineNodeStrategy: 数据汇聚方式：{}", node.getCombineDataType());
        // 数据存入 StorageDataVarMap, 供UI用
        String inDataToStorageMapVar = node.getDefineVarName();
        List<Map<String,Object>> dataList = (List<Map<String,Object>>)dataDto.getStorageDataVarMap().get(inDataToStorageMapVar);
        if (dataList==null) {
            dataList = new ArrayList<>();
        }

        // 需合并的数据变量
        String needCombineVars = node.getNeedCombineVars();
        List<String> needCombineVarList = Arrays.asList(needCombineVars.split(","));


        // 数据汇聚节点：汇聚方式：1：追加， 2：笛卡尔积
        if (node.getCombineDataType()==1) {
            for (String needCombineVar:needCombineVarList) {
                if (StringUtils.isNull(needCombineVar)) {continue;}
                Object o1 = executeScriptForResult(dataDto, needCombineVar);
                List<Map<String, Object>> sonList = (List<Map<String, Object>>)o1;//dataDto.getStorageDataVarMap().get(needCombineVar);
                dataList.addAll(sonList);
            }
        }else{
            /*
            a = [{'id':1, 'email':'x@x.cn'},{'id':2, 'email:y@y.cn'}]
            b = [{'msg':'消息'}]
            result = [{'id':1, 'email':'x@x.cn', 'msg':'消息'},{'id':2, 'email:y@y.cn', 'msg':'消息'}]
            */
            List<List<Map<String,Object>>> bigList = new ArrayList<>();
            for (String needCombineVar:needCombineVarList) {
                if (StringUtils.isNull(needCombineVar)) {continue;}
                Object o1 = executeScriptForResult(dataDto, needCombineVar);
                List<Map<String, Object>> sonList = (List<Map<String, Object>>)o1;//dataDto.getStorageDataVarMap().get(needCombineVar);
                dataList.addAll(sonList);
            }
            // 计算
            List<Map<String,Object>> resultList = calDiKaErJi(bigList);
            dataList.addAll(resultList);
        }

        // 数据存入 StorageDataVarMap, 供UI用
        dataDto.getStorageDataVarMap().put(inDataToStorageMapVar, dataList);
        dataDto.getLogList().add("保存数据在"+inDataToStorageMapVar+"里，记录数："+dataList.size());

        // 数据汇聚完成, 重置数据
        // dataDto.resetCombineInfo();

        return Result.builder(Combine_Ok);
    }

    private List<Map<String,Object>> calDiKaErJi(List<List<Map<String,Object>>> bigList) {
        // 取2项做运算
        List<Map<String,Object>> resultList = bigList.get(0);
        int bigListSize = bigList.size();
        for (int i=1; i<bigListSize; i++) {
            List<Map<String,Object>> nextList = bigList.get(i);
            cal(resultList, nextList);
        }
        return resultList;
    }

    private void cal(List<Map<String,Object>> resultList, List<Map<String,Object>> nextList) {
        List<Map<String,Object>> resultListTemp = new ArrayList<>();
        for (Map<String, Object> map1:resultList) {
            for (Map<String, Object> map2:nextList) {
                Map<String,Object> mapTemp = new HashMap<>();
                mapTemp.putAll(map1);
                mapTemp.putAll(map2);
                resultListTemp.add(mapTemp);
            }
        }
        resultList.clear();
        resultList.addAll(resultListTemp);
    }

    public static void main(String[] args) {
        System.out.println(1111);

        List<List<Map<String,Object>>> bigList = new ArrayList<>();
        List<Map<String,Object>> list1 = new ArrayList<>();
        Map<String,Object> map;
        map = new HashMap<>();
        map.put("email", "x@x.cn");
        list1.add(map);
        map = new HashMap<>();
        map.put("email", "y@y.cn");
        list1.add(map);


        List<Map<String,Object>> list2 = new ArrayList<>();
        map = new HashMap<>();
        map.put("msg", "hello world 1");
        list2.add(map);
        map = new HashMap<>();
        map.put("msg", "hello world 2");
        list2.add(map);

        List<Map<String,Object>> list3 = new ArrayList<>();
        map = new HashMap<>();
        map.put("mobile", "13511111111");
        list3.add(map);
        map = new HashMap<>();
        map.put("mobile", "13522222222");
        list3.add(map);

        bigList.add(list1);
        bigList.add(list2);
        bigList.add(list3);

        System.out.println(list1);
        System.out.println(list2);
        List<Map<String,Object>> resultList = new ControllerCombineNodeStrategy().calDiKaErJi(bigList);
        System.out.println(resultList);
    }

}
